package com.hk.context;

import com.hk.Mgr.web.message.order.AddCardRes;
import com.hk.Mgr.web.message.order.PaymentReq;
import com.hk.api.exceptions.ValidateException;
import com.hk.base.ResponseBase;
import com.hk.commons.*;
import com.hk.commons.enm.CompanyEnum;
import com.hk.commons.entity.pay.FM;
import com.hk.commons.entity.product.HistoryPayment;
import com.hk.commons.entity.product.Payment;
import com.hk.commons.entity.sys.SysUser;
import com.hk.commons.utils.HttpUtil;
import com.hk.commons.utils.sys.MD5Crypter;
import com.hk.service.order.IHistoryPayment;
import com.hk.service.order.IPayment;
import com.hk.service.sys.ISysUser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 支付方式相关
 * Created by Evan on 2017/10/17.
 * @author Evan
 */
@Service
public class PaymentContext {
    @Autowired
    private ISysUser userService;

    @Autowired
    private IPayment paymentService;

    @Autowired
    private IHistoryPayment historyPaymentService;

    private Logger logger = LoggerFactory.getLogger(PaymentContext.class);

    @Value("${hk.logsBaseUrl}")
    private String logsBaseUrl;

    @Value("${fy.scheme}")
    private String scheme;

    @Value("${fy.valiFour}")
    private String realUrl;

    @Value("${fy.getBankPath}")
    private String getBankpath;

    @Value("${fy.Secret}")
    private String fySecret;

    @Value("${fy.mchntCd}")
    private String fyMchntCd;

    /**
     * 盈米绑卡成功后再调用该接口保存到HK数据库
     * @param req
     * @return
     */
    public ResponseBase<AddCardRes> addCard(PaymentReq req) {
        ResponseBase<AddCardRes> resq = new ResponseBase<>();
        AddCardRes addCardRes = new AddCardRes();
        if(req == null){
            return resq;
        }

        logger.info("addCard params,userId={},accountId={},identityNo={},phone={},paymentNo={},paymentMethodId={}"
                ,req.getUserId(),req.getAccountId(),req.getIdentityNo(),req.getPhone(),req.getPaymentNo(),req.getPaymentMethodId());
        SysUser user = userService.findById(req.getUserId());
        if(user == null){
            logger.error("绑卡用户不存在");
            resq.setResult(addCardRes);
            resq.setMsg(ResultCode.USER_NOT_EXIST.getMsg());
            resq.setResultCode(ResultCode.USER_NOT_EXIST.getCode());
            return resq;
        }

        //写入txt文件
        try{
            yingmiReturnCardFile(req,user);
        }catch (Exception e){
            logger.error("写绑上文件失败！",e);
        }

        if (StringHelper.isNotEmpty(req.getIdentityNo()) && StringHelper.isNotEmpty(user.getIdentity())
                && (!ifSameUpper(req.getIdentityNo(), user.getIdentity()))) {
            logger.info("用户身份证信息和银行卡身份证信息不一致,userId={}", user.getId());
            addCardRes.setResult(false);
            resq.setResult(addCardRes);
            resq.setResultCode(ResultCode.PARAM_ERROR.getCode());
            resq.setMsg("用户身份证信息和银行卡身份证信息不一致！");
            return resq;
        }

        if (checkNeedUpdateUser(req,user)) {
            try {
                // 关联更新用户个人身份证号和真实姓名
                logger.info("update user info");
                userService.upUserByPayment(req.getUserId(), req.getAccountId(), req.getIdentityNo(), req.getAccountName());
                user = userService.findById(req.getUserId());
            } catch (Exception e) {
                logger.error("关联更新用户身份证号和姓名异常", e);
            }
        }

        // 判断用户是否已绑卡，有绑卡则不能再次绑卡。盈米可以绑多张卡，只要判断该卡号是否已被绑定
        HqlFilter paymentFilter = new HqlFilter();
        paymentFilter.addEQFilter("paymentNo", req.getPaymentNo());
        List<Payment> paymentList = paymentService.findByFilter(paymentFilter);
        if(chekExistCard(paymentList)){
            logger.info("该卡已被盈米绑定，不能再次绑卡！userId={},paymentNo={}", req.getUserId(), req.getPaymentNo());
            addCardRes.setResult(false);
            resq.setResult(addCardRes);
            resq.setMsg("该卡已被绑定，不能再次绑卡！");
            resq.setResultCode(ResultCode.PARAM_ERROR.getCode());
            return resq;
        }

        try {
            String identityNo = addPaymentTask(req, user, paymentList);

            addCardRes.setResult(true);
            addCardRes.setIdentityNo(identityNo);
            resq.setResult(addCardRes);
            resq.setResultCode(ResultCode.SUCC.getCode());

        }catch (Exception e){
            logger.error("AppPaymentCtrl add payment error!",e);
            logger.error("error info:  identity = {},accountName ={},paymentNo = {},phone = {}",req.getIdentityNo(),
                    req.getAccountName(),req.getPaymentNo(),req.getPhone());
            addCardRes.setResult(false);
            resq.setResult(addCardRes);
            resq.setResultCode(ResultCode.FAILED.getCode());
            resq.setMsg("绑卡异常！");
        }

        return resq;
    }

    /**
     * 盈米解绑成功后再调用该接口解绑HK数据库的数据
     * @param userId
     * @param paymentNo
     * @param paymentMethodId
     * @param phone
     * @return
     */
    public ResponseBase<Boolean> unbindYmCard(String userId, String paymentNo, String paymentMethodId, String phone){

        ResponseBase<Boolean> base = new ResponseBase<Boolean>();
        userId = userId.split(",")[0];
        logger.info("盈米解绑回调unbindYmCard入参userId={},paymentNo={},paymentMethodId={},phone={}",
                userId, paymentNo, paymentMethodId, phone);
        if (StringHelper.isEmpty(userId) || StringHelper.isEmpty(paymentNo)
                || StringHelper.isEmpty(paymentMethodId)
                || StringHelper.isEmpty(phone)) {
            base.setResultCode(ResultCode.PARAM_ERROR.getCode());
            base.setResult(false);
            base.setMsg("参数不能为空！");
            return base;
        }

        HqlFilter unbindFilter = new HqlFilter();
        unbindFilter.addEQFilter("userId", Long.valueOf(userId));
        unbindFilter.addEQFilter("paymentMethodId", paymentMethodId);
        List<Payment> paymentList = paymentService.findByFilter(unbindFilter);

        try {
            //修改支付表的状态
            updatePaymentToUnbind(paymentList);
            //修改用户绑卡状态
            updateUserBindStatus(Long.valueOf(userId));
            base.setMsg("解绑成功");
            base.setResultCode(ResultCode.SUCC.getCode());
            base.setResult(true);
        }catch (Exception e){
            logger.error("解绑盈米卡出现未知异常，paymentNo={}，paymentMethodId={}", paymentNo, paymentMethodId);
            logger.error("异常信息：", e);
            base.setMsg("解绑盈米卡失败");
            base.setResultCode(ResultCode.FAILED.getCode());
            base.setResult(false);
        }

        return base;
    }

    /**
     * 根据银行卡号查询银行信息
     * @param cardNum
     * @return
     */
    public FM getBankCardInfo(String cardNum){
        StringBuilder url = new StringBuilder();
        url.append(scheme).append("://");
        url.append(realUrl);
        url.append(getBankpath);

        StringBuilder allUrl = new StringBuilder();
        allUrl.append(fyMchntCd)
                .append("|")
                .append(cardNum)
                .append("|")
                .append(fySecret);
        String sign = MD5Crypter.md5Encrypt(allUrl.toString());

        StringBuilder param = new StringBuilder();
        param.append("<FM><MchntCd>")
                .append(fyMchntCd)
                .append("</MchntCd><Ono>")
                .append(cardNum)
                .append("</Ono><Sign>")
                .append(sign)
                .append("</Sign></FM>");

        Map<String ,String> params = new HashMap<>(1);
        params.put("FM",param.toString());
        String response = HttpUtil.postHttpForm(url.toString(),params,null);
        if(response == null){
            return  null;
        }

        logger.info("查询该银行卡号信息如下：Ono={},sb={}", cardNum, response);
        String resultString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
                + response.toLowerCase();
        BeanAndXMLTurn<FM> ff = new BeanAndXMLTurn<>();
        FM result = ff.XMLStringToBean(resultString, new FM());
        return result;
    }

    /**
     * 写入盈米绑卡返回记录到文件
     * @param  req
     * @param user
     */
    private void yingmiReturnCardFile(PaymentReq req,SysUser user){
        Long cts = System.currentTimeMillis();
        String pathName = "YingmiReturnCard-"
                + DateUtil.transferLongToDate("yyyyMM", cts) + ".txt";
        String filePath = logsBaseUrl+"/hkLogRecord/";

        StringBuffer buffer = new StringBuffer();
        buffer.append(DateUtil.transferLongToDate("yyyy-MM-dd HH:mm:ss", cts));
        buffer.append("----盈米返回绑卡用户信息:  identity = ").append(req.getIdentityNo());
        buffer.append(",accountName = ").append(req.getAccountName());
        buffer.append(",paymentNo = ").append(req.getPaymentNo());
        buffer.append(",phone = ").append(req.getPhone());
        buffer.append(",accountId= ").append(req.getAccountId());
        buffer.append(",userId =").append(req.getUserId());
        String userPhone = user.getName();
        if (!(req.getPhone().equals(user.getName()))) {
            buffer.append(",手机号不一致！注册手机=" ).append(userPhone);
        }
        buffer.append("\r\n");

        FileUtil.writeFile(filePath,pathName,buffer.toString());
    }

    /**
     * 成功绑卡时记录红绑上信息
     * @param req
     */
    private void writeAddCardFile(PaymentReq req){
        Long cts = System.currentTimeMillis();
        String pathName = "hkAddCardRecord-"
                + DateUtil.transferLongToDate("yyyyMM", cts) + ".txt";
        String filePath = logsBaseUrl+"/hkLogRecord/";
        StringBuffer buffer = new StringBuffer();
        buffer.append(DateUtil.transferLongToDate("yyyy-MM-dd HH:mm:ss", cts));
        buffer.append("----绑卡用户信息:  identity = ").append(req.getIdentityNo());
        buffer.append(",accountName = ").append(req.getAccountName());
        buffer.append(",paymentNo = ").append(req.getPaymentNo());
        buffer.append(",phone = ").append(req.getPhone());
        buffer.append(",accountId= ").append(req.getAccountId());
        buffer.append(",userId =").append(req.getUserId());
        buffer.append("\r\n");

        FileUtil.writeFile(filePath,pathName,buffer.toString());

    }

    private boolean ifSameUpper(String oldIdent, String newIdent) {
        if (oldIdent.toLowerCase().equals(newIdent.toLowerCase())) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 检查是否要更新用户信息
     * @param req
     * @param user
     * @return
     */
    private boolean checkNeedUpdateUser(PaymentReq req,SysUser user){
        if(req == null || user == null){
            return false;
        }

        if(StringUtils.isBlank(user.getIdentity()) || StringUtils.isBlank(user.getRealName())){
            return true;
        }

        //accountId为空时要更新
        if(StringUtils.isNotBlank(req.getAccountId()) && StringUtils.isBlank(user.getAccountId())){
            return true;
        }

        if(StringUtils.isNotBlank(req.getAccountId()) && !req.getAccountId().equals(user.getAccountId())){
            return true;
        }

        return false;

    }

    /**
     * 检查是否已经绑过盈米卡
     * @param paymentList
     * @return
     */
    private boolean chekExistCard(List<Payment> paymentList){


        if(paymentList.isEmpty()){
            return false;
        }
        boolean result = paymentList.stream().anyMatch(p->{
            String ym = paymentService.getCardCompany(ConstantRoute.COMPANY_YINGMI, p);
            return CompanyEnum.CompanyEnum_4.getCode().equals(ym);
        });
        return result;
    }

    private String addPaymentTask(PaymentReq req,SysUser user,List<Payment> existPaymentList){
        String identityNo = req.getIdentityNo();
        Payment newPayment = addOrUpdatePayment(req,user,existPaymentList);
        try {
            HistoryPayment historyPayment=new HistoryPayment();
            historyPayment.setCompany(ConstantRoute.COMPANY_YINGMI);
            historyPayment.setPaymentType(CardStatusCode.PAYMENT_TYPE_ADD);
            historyPayment.setNewBankNo(req.getPaymentNo());
            historyPayment.setUserId(Long.valueOf(req.getUserId()));
            historyPayment.setPaymentId(newPayment.getId());
            historyPayment.setNewBankName(newPayment.getBankName());
            historyPayment.setStatus(1);
            historyPaymentService.add(historyPayment);
        }catch (Exception e){
            logger.error("AppPaymentCtrl addtoHistory payment error!",e);
        }

        //记录成功绑
        try {
            writeAddCardFile(req);
        }catch (Exception e){
            logger.error("写绑卡文本文件失败！", e);
        }

        if(StringUtils.isBlank(identityNo)){
            if(StringUtils.isNotBlank(user.getIdentity())){
                identityNo = user.getIdentity();
                logger.info("盈米返回身份证为空,n次绑卡！用户身份证identity={}", identityNo);
            }else {
                identityNo = "";
            }

        }
        return  identityNo;
    }

    /**
     * 保存或更新支付方式
     * @param req
     * @param user
     * @param existPaymentList
     * @return
     */
    private Payment addOrUpdatePayment(PaymentReq req,SysUser user,List<Payment> existPaymentList){
        if(req == null || user == null || existPaymentList == null){
            logger.error("addOrUpdatePayment error");
            return null;
        }

        if(existPaymentList.isEmpty()){
            // 在支付信息表里添加记录
            Payment payment = new Payment();
            payment.setUserId(req.getUserId());
            payment.setAccountName(req.getAccountName());
            payment.setPhone(req.getPhone());
            payment.setUserRegistPhone(user.getName());
            payment.setPaymentNo(req.getPaymentNo());
            payment.setPaymentMethodId(req.getPaymentMethodId());
            payment.setCts(System.currentTimeMillis());
            payment.setCardStatus(CardStatusCode.PAYMENT_DISPLAY_SHOW);
            Integer bankId = 0;
            if (StringHelper.isNotEmpty(req.getBankId())) {

                bankId = Integer.valueOf(req.getBankId());
            }
            payment.setBankId(bankId);
            payment.setIdentityNo(req.getIdentityNo());
            //身份证为空时，从已绑卡中获取
            if(StringUtils.isBlank(req.getIdentityNo())){
                payment.setIdentityNo(findIdentityFromPayment(req.getUserId()));
            }

            paymentService.setAddCardCompany(ConstantRoute.COMPANY_YINGMI, payment);
            fillBankInfo(payment,req.getPaymentNo());
            paymentService.add(payment);
            try {
                user.setTieCard(CardStatusCode.PAYMENT_DISPLAY_SHOW);
                userService.update(user);
            } catch (Exception e) {
                logger.error("更新用户表异常！", e);
            }
            return  payment;

        }else {
            Payment existPayment = existPaymentList.get(0);
            existPayment.setCardStatus(CardStatusCode.PAYMENT_DISPLAY_SHOW);
            existPayment.setPaymentMethodId(req.getPaymentMethodId());
            existPayment.setCts(System.currentTimeMillis());
            // 更新银行预留手机号
            existPayment.setPhone(req.getPhone());
            paymentService.setAddCardCompany(ConstantRoute.COMPANY_YINGMI, existPayment);
            paymentService.update(existPayment);
            try {
                user.setTieCard(CardStatusCode.PAYMENT_DISPLAY_SHOW);
                userService.update(user);
            } catch (Exception e) {
                logger.error("更新用户表异常！", e);
            }
            return existPayment;
        }

    }

    /**
     * 填充银行卡信息
     * @param payment
     */
    private void fillBankInfo(Payment payment,String paymentNo){
        if(payment == null || StringUtils.isBlank(paymentNo)){
            return;
        }

        FM fm = getBankCardInfo(paymentNo);
        if(fm == null){
            return;
        }

        if(StringUtils.isBlank(fm.getCnm())){
            return;
        }

        // 卡类型
        payment.setCardType(fm.getCtp());
        // 银行名称
        payment.setBankName(fm.getCnm());
        // 银行机构号
        payment.setInsCard(fm.getInscd());
    }

    /**
     * 从支付方式获取身份证号
     * @param userId
     * @return
     */
    private String findIdentityFromPayment(Long userId){
        SysUser user = userService.findById(userId);
        if(user == null){
            return null;
        }

        String identity = user.getIdentity();
        if(StringUtils.isNotBlank(identity)){
            return null;
        }

        HqlFilter pFilter = new HqlFilter();
        pFilter.addEQFilter("userId", userId);
        pFilter.addSort("cts");
        pFilter.addOrder("desc");
        List<Payment> payList = paymentService.findByFilter(pFilter);
        Payment payment = payList.stream()
                .filter(p -> StringUtils.isNotBlank(p.getIdentityNo()))
                .findFirst()
                .orElse(new Payment());
        return payment.getIdentityNo();
    }

    /**
     * 更新支付表的解绑状态
     * @param paymentList
     */
    private void updatePaymentToUnbind(List<Payment> paymentList){
        if(paymentList == null || paymentList.isEmpty()){
            throw new ValidateException("查询不到该绑卡记录");
        }
        paymentList.stream().forEach(p ->{
            paymentService.changeCardStatus(ConstantRoute.COMPANY_YINGMI, p, CardStatusCode.UNBIND_CARD);
            p.setLastUseTime(System.currentTimeMillis());
            String hk = paymentService.getCardCompany(ConstantRoute.COMPANY_HUAKANG, p);
            String hc = paymentService.getCardCompany(ConstantRoute.COMPANY_HUOCHAI, p);
            if (!((ConstantRoute.COMPANY_HUAKANG + "").equals(hk) || (ConstantRoute.COMPANY_HUOCHAI + "").equals(hc))) {
                p.setCardStatus(CardStatusCode.PAYMENT_DISPLAY_HIDE);
            }

            paymentService.update(p);
            HistoryPayment historyPayment=new HistoryPayment();
            historyPayment.setCompany(ConstantRoute.COMPANY_YINGMI);
            historyPayment.setPaymentType(CardStatusCode.PAYMENT_TYPE_UNBIND);
            historyPayment.setOldBankName(p.getBankName());
            historyPayment.setOldBankNo(p.getPaymentNo());
            historyPayment.setUserId(p.getUserId());
            historyPayment.setPaymentId(p.getId());
            historyPayment.setStatus(1);
            historyPaymentService.add(historyPayment);
        });

    }


    /**
     * 解卡后，如果没有绑定的卡，用户绑卡状态变为末绑
     * @param userId
     */
    private void updateUserBindStatus(Long userId){
        HqlFilter userCardFilter = new HqlFilter();
        userCardFilter.addEQFilter("userId", Long.valueOf(userId));
        List<Payment> userCardList = paymentService.findByFilter(userCardFilter);
        boolean hasCardBind = userCardList
                .stream()
                .anyMatch(p ->p.getCardStatus() != CardStatusCode.PAYMENT_DISPLAY_HIDE);

        if(!hasCardBind){
            SysUser user = userService.findById(userId);
            if (user != null) {
                user.setTieCard(CardStatusCode.PAYMENT_DISPLAY_HIDE);
                userService.update(user);
            }
        }
    }
}
